//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<quad.h>
///	@path	~/src/lib/math/
///	@date	2008/11/18
///	@brief	.

#pragma once

#include "xeres.h"

#include "lib/math/vector.h"
#include "lib/math/rect.h"

namespace xeres {

	/*! 
		\class	Quad
		\brief	Encapsulates a quad with 4 points.
				0 -- 1
				2 -- 3
	*/
	class Quad
	{
	public:

		/// \ctor
		Quad( void ) {}

		/// \ctor
		Quad( const Vector<float>& p0 , const Vector<float>& p1 , const Vector<float>& p2 , const Vector<float>& p3 );

		/// \ctor
		Quad( const Quad& rhs )
		{
			m_p[0] = rhs.m_p[0];
			m_p[1] = rhs.m_p[1];
			m_p[2] = rhs.m_p[2];
			m_p[3] = rhs.m_p[3];
		}

		/// \ctor
		Quad( const Rect<float>& region , float z )
		{
			assert( !region.is_empty() );
			m_p[0].set( region.left() , region.top() , z );
			m_p[1].set( region.right() , region.top() , z );
			m_p[2].set( region.left() , region.bottom() , z );
			m_p[3].set( region.right() , region.bottom() , z );
		}

	public:

		/// \brief	Access vertex.
		const Vector<float>& vertex( int index ) const
		{
			return m_p[index];
		}

		/// \brief	Access vertex.
		Vector<float>& vertex( int index )
		{
			return m_p[index];
		}

		/// \brief	Calculate normal of quad.
		Vector<float> normal( void ) const
		{
			Vector<double> ng;
			ng.cross( m_p[2] - m_p[0] , m_p[1] - m_p[0] );
			ng.normalize();
			return Vector<float>( ng );
		}

		/// \brief	Access as array.
		const float * as_array( void ) const
		{
			return m_p[0].f;
		}

		/// \brief	Access as array.
		float * as_array( void )
		{
			return m_p[0].f;
		}

		/// \brief	Fast access of vertices.
		const Vector<float>& v00( void ) const { return m_p[0]; }
		const Vector<float>& v10( void ) const { return m_p[1]; }
		const Vector<float>& v11( void ) const { return m_p[2]; }
		const Vector<float>& v01( void ) const { return m_p[3]; }

		struct _Intersection
		{
			Vector<float>	inter;
			float			t;
			float			u;
			float			v;
		};

		/// \brief	Intersect with ray.
		bool intersect( const Vector<float>& o , const Vector<float>& d , const Vector<float>& ng , bool double_side , _Intersection& in ) const;

	protected:

		/// \brief	Internal intersect method.
		bool _intersect1( const Vector<float>& o , const Vector<float>& d , const Vector<float>& ng , bool double_side , _Intersection& in ) const;

		/// \brief	Internal intersect method.
		bool _intersect2( const Vector<float>& o , const Vector<float>& d , const Vector<float>& ng , bool double_side , _Intersection& in ) const;
		
		//@ data
		Vector<float>		m_p[4];
	};

} // namespace xeres
